package com.manlitech.cloudboot.oauth.config;

import com.manlitech.cloudboot.oauth.config.filter.JwtAuthenticateFilter;
import com.manlitech.cloudboot.oauth.config.filter.JwtAuthorizationFilter;
import com.manlitech.cloudboot.oauth.config.handler.MyAccessDeniedHandler;
import com.manlitech.cloudboot.oauth.config.handler.MyAuthenticationEntryPoint;
import com.manlitech.cloudboot.oauth.config.handler.MyLogoutSuccessHandler;
import com.manlitech.cloudboot.oauth.service.impl.UserDetailServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;

import javax.annotation.Resource;

/**
 * @author shensg
 * @date 2021/7/7 17:37
 */
@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    /**
     * 未登陆时返回 JSON
     */
    @Resource
    private MyAuthenticationEntryPoint myauthenticationEntryPoint;
    /**
     * 退出登录
     */
    @Resource
    private MyLogoutSuccessHandler mylogoutSuccessHandler;
    /**
     * 无权访问返回的
     */
    @Resource
    private MyAccessDeniedHandler myaccessDeniedHandler;

    @Resource
    private UserDetailServiceImpl myUserDetailsService;

    /*** 当前配置为form表单登录认证方式*/
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //禁用跨站csrf攻击防御
        // 如果客户端不是浏览器，则可能需要禁用CSRF保护。它不应该影响性能。过滤器（或其他组件）将从请求处理链中删除，以使该功能不可用，它确实会使请求更加冗长。
        http.csrf().disable()
                //前后端分离采用JWT ,不需要session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                //配置登录后的权限
                .authorizeRequests()
                    // 用户可任意访问不需要限制
                    .antMatchers("/login","/success","/hello").permitAll()
                    // 除上面外的请求全部需要鉴权认证-;
                    //authenticated()要求在执行请求要求必须已登录
                    .anyRequest().authenticated()
                .and()
                //开启表单登录
                .formLogin()
                    .loginProcessingUrl("/login")
                .and()
                //无访问权限，请先登录
                .httpBasic()
                    .authenticationEntryPoint(myauthenticationEntryPoint)
                .and()
                .addFilter(new JwtAuthenticateFilter(authenticationManager()))
                .addFilter(new JwtAuthorizationFilter(authenticationManager()))
                .logout()
                //退出
                    .logoutUrl("/logout")
                    .logoutSuccessHandler(mylogoutSuccessHandler).permitAll();
        //无权访问返回的
        http.exceptionHandling().accessDeniedHandler( myaccessDeniedHandler);
    };

    // 配置数据库认证方法, http basic登录基础配置
    @Override
    public  void  configure(AuthenticationManagerBuilder auth)  throws  Exception {
        //调用DetailsService完成用户身份验证              设置密码加密方式
        auth.userDetailsService(myUserDetailsService).passwordEncoder(getBCryptPasswordEncoder() );
    }

    @Bean
    public BCryptPasswordEncoder getBCryptPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }
}
